using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine.UIElements;
using System.Linq;

namespace DA.AnimGraph.Editor {

    internal abstract class InspectorDataSource {
        protected Dictionary<string, VisualElement> inspectorWidgets;
        public virtual void DrawUI(VisualElement container, AGEContext ageContext, Action inspectorChangeCallback) {
            var fields = this.GetType().GetFields();
            inspectorWidgets = new();

            var fieldTupple = fields.Where(x => {
                var attr = x.GetCustomAttribute<InspectorFieldAttribute>();
                return attr != null;
            }).Select(x => {
                return (x, x.GetCustomAttribute<InspectorFieldAttribute>());
            }).OrderBy(x => x.Item2.order).ToArray();

            foreach (var (fieldInfo, attr) in fieldTupple) {
                // var attr = fieldInfo.GetCustomAttribute<InspectorFieldAttribute>();
                if (attr != null) {
                    string name = attr.label ?? fieldInfo.Name;
                    string key = attr.tag ?? fieldInfo.Name;
                    if (attr.tag != null) {
                        var ele = CustomizeField(name, attr, fieldInfo, ageContext, inspectorChangeCallback);
                        if (ele != null) {
                            AddToContainer(container, ele, ageContext);
                            inspectorWidgets.Add(key, ele);
                            continue;
                        }
                    }

                    var source = fieldInfo.GetValue(this);
                    if (source == null) {
                        continue;
                    }

                    bool isList = attr.isList;
                    if (!isList) {
                        var ele = InspectorFieldFactory.SwitchField(fieldInfo.FieldType);
                        if (ele != null) {
                            ele.Init(name, source, ageContext, inspectorChangeCallback);
                            AddToContainer(container, ele, ageContext);
                            inspectorWidgets.Add(key, ele);
                        }
                    } else {
                        var ele = InspectorFieldFactory.SwitchListField(name, attr, this, fieldInfo, ageContext, inspectorChangeCallback);
                        if (ele != null) {
                            AddToContainer(container, ele, ageContext);
                            inspectorWidgets.Add(key, ele);
                        }
                    }
                }
            }
            OnDrawUIFinish(ageContext);
        }

        protected virtual void OnDrawUIFinish(AGEContext ageContext) { }

        public virtual void OnClearUI() { }

        protected virtual VisualElement CustomizeField(string name, InspectorFieldAttribute fieldAttribute, FieldInfo fieldInfo, AGEContext ageContext, Action inspectorChangeCallback) {
            return null;
        }

        void AddToContainer(VisualElement container, VisualElement element, AGEContext context) {
            AGEGlobal.GetInstance().style.SS_InspectorField(element);
            container.Add(element);
        }

    }

}